package com.lagou.config;

import com.lagou.mapper.Delete;
import com.lagou.mapper.Insert;
import com.lagou.mapper.Mapper;
import com.lagou.mapper.Select;
import com.lagou.mapper.Update;
import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;
import com.lagou.pojo.SqlCommandType;
import com.lagou.utils.ResolverUtil;
import org.dom4j.DocumentException;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Set;

public class AnnoMapperBuilder {

    private Configuration configuration;

    public AnnoMapperBuilder(Configuration configuration) {
        this.configuration =configuration;
    }

    public void parse(String basePackage) throws DocumentException {
        parse(basePackage, Mapper.class);
    }

    public void parse(String basePackage,Class<?> superType) throws DocumentException {
        ResolverUtil<Class<?>> resolverUtil = new ResolverUtil<Class<?>>();
        resolverUtil.find(new ResolverUtil.IsA(superType), basePackage);
        Set<Class<? extends Class<?>>> mapperSet = resolverUtil.getClasses();
        for (Class<?> mapperClass : mapperSet) {
            addMapper(mapperClass);
        }
    }

    public void addMapper(Class<?> mapperClass){
        String namespace = mapperClass.getName();

        Method[] methods = mapperClass.getMethods();
        for (Method method : methods) {
            Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
            SqlCommandType sqlCommandType = null;
            String sqlText = null;

            for (Annotation declaredAnnotation : declaredAnnotations) {
                Class<? extends Annotation> aClass = declaredAnnotation.annotationType();
                if(aClass.equals(Select.class)){
                    Select select = (Select)declaredAnnotation;
                    sqlText = select.value();
                    sqlCommandType = SqlCommandType.SELECT;
                }else if(aClass.equals(Update.class)){
                    Update update = (Update)declaredAnnotation;
                    sqlText = update.value();
                    sqlCommandType = SqlCommandType.UPDATE;
                }else if(aClass.equals(Delete.class)){
                    Delete delete = (Delete)declaredAnnotation;
                    sqlText = delete.value();
                    sqlCommandType = SqlCommandType.DELETE;
                }else if(aClass.equals(Insert.class)){
                    Insert insert = (Insert)declaredAnnotation;
                    sqlText = insert.value();
                    sqlCommandType = SqlCommandType.INSERT;
                }

            }

            if(sqlCommandType == null){
                continue;
            }

            String id = method.getName();
            String resultType = method.getReturnType().getName();
            Class<?>[] parameterTypes = method.getParameterTypes();
            if(parameterTypes.length > 1){
                throw new RuntimeException("自定义mapper暂时只支持一个参数," + method);
            }
            String paramterType = parameterTypes[0].getName();

            MappedStatement mappedStatement = new MappedStatement.Builder()
                    .id(id)
                    .resultType(resultType)
                    .paramterType(paramterType)
                    .sql(sqlText)
                    .sqlCommandType(sqlCommandType)
                    .build();

            String key = namespace+"."+id;
            configuration.getMappedStatementMap().put(key,mappedStatement);
            configuration.getAllMapper().add(mapperClass);
        }
    }
}
